package com.brillilab.service.logic.method;

import com.brillilab.common.alioss.OssFileEnum;
import com.brillilab.common.constant.ResultEnum;
import com.brillilab.common.entity.PageVo;
import com.brillilab.common.exceptions.BrillilabException;
import com.brillilab.domain.enums.method.MethodDealStateEnum;
import com.brillilab.domain.enums.method.MethodSourceEnum;
import com.brillilab.domain.po.lab.Lab;
import com.brillilab.domain.po.lab.LabMember;
import com.brillilab.domain.po.method.Method;
import com.brillilab.domain.po.method.MethodShare;
import com.brillilab.domain.po.method.MethodType;
import com.brillilab.domain.po.system.FileManage;
import com.brillilab.domain.po.user.Users;
import com.brillilab.domain.vo.lab.LabMemberVo;
import com.brillilab.domain.vo.method.*;
import com.brillilab.domain.vo.user.UserInfoVo;
import com.brillilab.service.core.lab.ILabMemberService;
import com.brillilab.service.core.lab.ILabService;
import com.brillilab.service.core.method.*;
import com.brillilab.service.core.system.IFileManageService;
import com.brillilab.service.logic.user.UsersLogic;
import com.brillilab.service.module.message.producer.MessageProducer;
import com.brillilab.service.module.message.template.impl.method.MemberMethodToShareOtherTemp;
import com.brillilab.service.module.message.template.impl.method.MemberShareMethodTemp;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author wuzhiyu
 * @Title: MethodShareLogic
 * @ProjectName brill_lab
 * @Description: TODO
 * @date 2019/2/2313:43
 */
@Service
@Transactional
public class MethodShareLogic {

    @Resource
    private IMethodShareService methodShareService;
    @Resource
    private IMethodService methodService;
    @Resource
    private ILabMemberService labMemberService;
    @Resource
    private MethodLogic methodLogic;
    @Resource
    private IMethodTypeService methodTypeService;
    @Resource
    private IMethodPhaseService methodPhaseService;
    @Resource
    private IMethodStepService methodStepService;
    @Resource
    private MethodRecommendLogic methodRecommendLogic;
    @Resource
    private MethodTypeLogic methodTypeLogic;
    @Resource
    private UsersLogic usersLogic;
    @Resource
    private ILabService labService;
    @Resource
    private MessageProducer messageProducer;
    @Resource
    private IFileManageService fileManageService;

    /**
     * @return boolean
     * @Description: 分享方法
     * @Params: [methodShareTo, user]
     * @author wuzhiyu
     * @date 2019/2/26 17:23
     */
    public boolean share(MethodShareTo methodShareTo, UserInfoVo user) {
        List<Method> methodList = methodService.listByIdList(methodShareTo.getMethodIdList(), null);
        if (CollectionUtils.isEmpty(methodList) || methodList.size() != methodShareTo.getMethodIdList().size()) {
            throw new BrillilabException(ResultEnum.DATA_NOT_EXIST);
        }
        LabMember labMember = labMemberService.selectById(methodShareTo.getReceiverId());
        if (labMember == null || !labMember.getLabId().equals(user.getLabId())) {
            throw new BrillilabException(ResultEnum.DATA_NOT_EXIST);
        }
        List<MethodShare> shareList = new ArrayList<>();
        methodShareTo.getMethodIdList().forEach(i -> {
            MethodShare share = new MethodShare();
            share.setMethodId(i);
            share.setReceiveMemberId(methodShareTo.getReceiverId());
            share.setShareMemberId(user.getLabMemberId());
            share.setShareTime(new Date());
            share.setState(MethodDealStateEnum.WaiteDeal.getState());
            shareList.add(share);
        });
        boolean b = methodShareService.addList(shareList);
        if (b) {
            Lab labInfo = labService.selectById(user.getLabId());
            //实验室管理员ID
            Long adminUserId = labInfo != null ? labInfo.getOwnerId() : 0;

            //分享成功，执行消息推送
            shareList.forEach(m -> {
                //分享目标（接受人）
                LabMember toLabMember = labMemberService.selectById(m.getReceiveMemberId());
                //获取方法信息
                Method methodInfo = methodService.getById(m.getMethodId());
                String methodName = methodInfo != null ? methodInfo.getName() : "";

                //操作人是方法所有者
                if (methodInfo.getUserId() > 0 && methodInfo.getUserId().equals(user.getId())) {
                    //消息推送
                    MemberShareMethodTemp memberShareMethodTemp = new MemberShareMethodTemp(user.getLabId(), toLabMember.getUserId(), toLabMember.getId(), user.getName(), methodName, m.getId());
                    messageProducer.sendMessagePush(memberShareMethodTemp);
                } else {
                    //操作人是管理员
                    if (adminUserId > 0 && user.getId().equals(adminUserId)) {
                        //成员方法被管理员分享给其他成员
                        Users shareUser = usersLogic.getUser(methodInfo.getUserId());
                        MemberMethodToShareOtherTemp memberMethodToShareOtherTemp = new MemberMethodToShareOtherTemp(user.getLabId(), toLabMember.getUserId(), toLabMember.getId(), user.getName(), shareUser.getName(), methodName, m.getId());
                        messageProducer.sendMessagePush(memberMethodToShareOtherTemp);
                    }
                }
            });
        }
        return b;
    }

    /**
     * @return com.brillilab.domain.vo.method.MethodShareInfo
     * @Description: 获取分享给我的方法详情
     * @Params: [shareId, user]
     * @author wuzhiyu
     * @date 2019/2/26 17:23
     */
    public MethodShareInfo getShareInfo(Long shareId, UserInfoVo user) {
        MethodShare share = methodShareService.getByIdAndReceiveMemberId(shareId, user.getLabMemberId());
        Assert.notNull(share, "数据不存在");
        MethodDetail methodDetail = methodLogic.getMethodDetail(share.getMethodId(), null, user.getLabId());
        MethodShareInfo info = new MethodShareInfo();
        info.setMethodDetail(methodDetail);
        MethodType third = methodTypeService.getMethodTypeById(methodDetail.getMethodTypeId());
        MethodType second = methodTypeService.getMethodTypeById(third.getSecondId());
        MethodType first = methodTypeService.getMethodTypeById(third.getFirstId());
        info.setFirstTypeName(first.getName());
        info.setSecondTypeName(second.getName());
        info.setThirdTypeName(third.getName());
        info.setShareTime(share.getShareTime());
        info.setState(share.getState());
        if (share.getState().equals(MethodDealStateEnum.WaiteDeal.getState())) {
            info.setStateStr(MethodDealStateEnum.WaiteDeal.getName());
        } else if (share.getState().equals(MethodDealStateEnum.Accept.getState())) {
            info.setStateStr(MethodDealStateEnum.Accept.getName());
            info.setAcceptTime(share.getUpdateTime());
        } else {
            info.setStateStr(MethodDealStateEnum.Refuse.getName());
        }
        LabMemberVo labMemberVo = labMemberService.selectMemberVo(share.getShareMemberId());
        info.setShareName(labMemberVo.getUserName());
        return info;
    }

    /**
     * @return boolean
     * @Description: 接受或拒绝分享
     * @Params: [deal, user]
     * @author wuzhiyu
     * @date 2019/2/26 17:24
     */
    public boolean deal(MethodShareDeal deal, UserInfoVo user) {
        MethodShare share = methodShareService.getByIdAndReceiveMemberId(deal.getShareId(), user.getLabMemberId());
        Assert.notNull(share, "数据不存在");
        Assert.isTrue(share.getState().equals(MethodDealStateEnum.WaiteDeal.getState()), "数据已处理过");
        Method oriMethod = methodService.getById(share.getMethodId());
        Assert.notNull(oriMethod, "数据不存在");
        if (deal.getState().equals(MethodDealStateEnum.Accept.getState())) {
            Long newMethodId = null;
            MethodShare accept = new MethodShare();
            accept.setState(MethodDealStateEnum.Accept.getState());
            accept.setId(share.getId());
            methodShareService.updateById(accept);
            LabMemberVo labMemberVo = labMemberService.selectMemberVo(share.getShareMemberId());
            if (!StringUtils.isEmpty(deal.getNewName())) {
                oriMethod.setName(deal.getNewName());
            }
            if (0 == deal.getExist() || 2 == deal.getExist() || 3 == deal.getExist() || 4 == deal.getExist()) {
                newMethodId = methodRecommendLogic.dealToMyNewMethod(user, oriMethod, MethodSourceEnum.SHARE, null, share.getCreateTime(), labMemberVo.getUserName(), deal.getTypeId());
            } else {
                newMethodId = methodLogic.saveAcceptMethodToNewVersion(user, oriMethod, deal.getMyExistInitMethodId(), share.getCreateTime());
            }
            //fixme 附件处理 (只有接受时处理附件)
            if (newMethodId != null && deal.getState() == 1) {
                List<FileManage> fileList = fileManageService.selectList(OssFileEnum.Method, share.getMethodId());
                if (!CollectionUtils.isEmpty(fileList)) {
                    List<FileManage> copies = new ArrayList<>();
                    for (FileManage fileManage : fileList) {
                        fileManage.setId(null);
                        fileManage.setReferDataId(newMethodId);
                        fileManage.setUserId(user.getId());
                        fileManage.setLabId(user.getLabId());
                        fileManage.setCreateTime(null);
                        copies.add(fileManage);
                    }
                    fileManageService.insertBatch(copies);
                }
            }
        }
        MethodShare dealState = new MethodShare();
        dealState.setState(deal.getState());
        dealState.setId(share.getId());
        methodShareService.updateById(dealState);
        return true;
    }

    /**
     * @return com.brillilab.common.entity.PageVo<com.brillilab.domain.vo.method.MethodShareFromListItem>
     * @Description: 分享给我的方法列表
     * @Params: [user, pageIndex, rows]
     * @author wuzhiyu
     * @date 2019/2/26 17:24
     */
    public PageVo<MethodShareFromListItem> listShareToMe(UserInfoVo user, Integer state, Integer pageIndex, Integer rows) {
        PageVo<MethodShare> page = methodShareService.listSharePaged(user.getLabMemberId(), state, pageIndex, rows, true, true);
        List<MethodShareFromListItem> content = new ArrayList<>();
        PageVo<MethodShareFromListItem> result = new PageVo<>(page.getPageNum(), page.getPageSize(), page.getTotalRow(), content);
        if (!CollectionUtils.isEmpty(page.getContent())) {
            List<LabMemberVo> memList = labMemberService.selectList(user.getLabId(), null);
            List<Long> methodIdList = page.getContent().stream().map(MethodShare::getMethodId).distinct().collect(Collectors.toList());
            List<Method> methodList = methodService.listByIdList(methodIdList, null);
            page.getContent().forEach(s -> {
                MethodShareFromListItem item = new MethodShareFromListItem();
                item.setId(s.getId());
                item.setMethodName(methodList.stream().filter(m -> m.getId().equals(s.getMethodId())).map(Method::getName).findFirst().get());
                item.setSharerName(memList.stream().filter(m -> m.getLabMemberId().equals(s.getShareMemberId())).map(LabMemberVo::getUserName).findFirst().get());
                item.setShareTime(s.getShareTime());
                item.setState(s.getState());
                item.setFirstTypeId(s.getFirstTypeId());
                item.setSuccessCount(s.getSuccessCount());
                item.setExportCount(s.getExportCount());
                item.setSuccessRate(s.getSuccessRate());
                if (s.getState().equals(MethodDealStateEnum.WaiteDeal.getState())) {
                    item.setStateStr(MethodDealStateEnum.WaiteDeal.getName());
                } else if (s.getState().equals(MethodDealStateEnum.Accept.getState())) {
                    item.setStateStr(MethodDealStateEnum.Accept.getName());
                } else {
                    item.setStateStr(MethodDealStateEnum.Refuse.getName());
                }
                content.add(item);
            });
        }
        return result;
    }

    /**
     * @return com.brillilab.common.entity.PageVo<com.brillilab.domain.vo.method.MethodShareListItem>
     * @Description: 我分享的方法列表
     * @Params: [user, pageIndex, rows]
     * @author wuzhiyu
     * @date 2019/2/26 17:24
     */
    public PageVo<MethodShareListItem> listMyShare(UserInfoVo user, Integer pageIndex, Integer rows, boolean isDesc) {
        PageVo<MethodShare> page = methodShareService.listSharePaged(user.getLabMemberId(), null, pageIndex, rows, false, isDesc);
        List<MethodShareListItem> content = new ArrayList<>();
        PageVo<MethodShareListItem> result = new PageVo<>(page.getPageNum(), page.getPageSize(), page.getTotalRow(), content);
        result.setContent(content);
        if (!CollectionUtils.isEmpty(page.getContent())) {
            List<Long> methodIdList = page.getContent().stream().map(MethodShare::getMethodId).distinct().collect(Collectors.toList());
            List<Method> methodList = methodService.listByIdList(methodIdList, null);
            page.getContent().forEach(s -> {
                MethodShareListItem item = new MethodShareListItem();
                item.setNameString(methodList.stream().filter(m -> m.getId().equals(s.getMethodId())).map(Method::getName).findFirst().get());
                item.setReceiverName(s.getReceiverName());
                item.setShareTime(s.getShareTime());
                item.setFirstTypeId(s.getFirstTypeId());
                content.add(item);
            });
        }
        return result;
    }
}
